using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Globalization;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TextManager.Interop;
using System.Windows.Forms;
using Microsoft.VisualStudio.Text.Tagging;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Formatting;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.Editor;
using System.Collections.Generic;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.VCCodeModel;
using System.Text;
using System.Drawing;
using EnvDTE;
using EnvDTE80;
using System.IO;
using System.Reflection;


namespace FunctionBar
{

    public enum MatchType
    {
        TABLE,
        FUNCTION,
        CONSTRUCTOR,
        DESTRUCTOR,
        COMMENT,
        AUTO
    }

    // we store the list of images used in any of the dropdown bars
    // in  a singleton.
    public sealed class FunImages
    {
        private static readonly FunImages instance = new FunImages();

        public ImageList images = new ImageList();

        private FunImages() {

            images.Images.Add(Properties.VSPackage.f);
            images.Images.Add(Properties.VSPackage.f2);
            images.Images.Add(Properties.VSPackage.c);
            images.Images.Add(Properties.VSPackage.t);
            images.Images.Add(Properties.VSPackage.empty);
            images.Images.Add(Properties.VSPackage.f3);
            images.Images.Add(Properties.VSPackage.f4);
        }


        public static FunImages Instance
        {
            get
            {
                return instance;
            }
        }

    }

    
    public abstract class FunBar : IVsDropdownBarClient, IVsCoTaskMemFreeMyStrings
    {

        public SVsServiceProvider ServiceProvider;
        public IVsEditorAdaptersFactoryService EditorAdaptersFactoryService;

        public abstract uint nentries();

        public int GetComboAttributes(int iCombo, out uint pcEntries, out uint puEntryType, out IntPtr phImageList)
        {
            pcEntries = nentries();
            puEntryType = (uint)DROPDOWNENTRYTYPE.ENTRY_ATTR | (uint)DROPDOWNENTRYTYPE.ENTRY_IMAGE;
            //phImageList = (IntPtr) null;

            phImageList = FunImages.Instance.images.Handle;

            return 0;
        }

        public abstract int GetEntryText(int iCombo, int iIndex, out string ppszText);
        public abstract int GetEntryAttributes(int iCombo, int iIndex, out uint pAttr);
        public abstract int GetEntryImage(int iCombo, int iIndex, out int piImageIndex);
        public abstract int OnItemChosen(int iCombo, int iIndex);


        public abstract void refresh_functions();
        public abstract void calc_caret_pos();


        public int GetComboTipText(int iCombo, out string pbstrText)
        {
            pbstrText = "";
            return 0;
        }


        public IVsTextView vsTextView = null;
        public void refresh_if_needed()
        {

            if (null == vsTextView) return;
            IWpfTextView wview = EditorAdaptersFactoryService.GetWpfTextView(vsTextView);
            ITextSnapshot shot = wview.TextSnapshot;

            if (shot.Version.VersionNumber != last_version)
            {
                last_version = shot.Version.VersionNumber;

                // this is probably a miserably inefficient way to do this, but, 
                // as long as i'm careful about *when* i do it, inefficiency shouldn't matter too much.
                file_data = shot.GetText();

                if (file_data != null) 
                    refresh_functions();
            }
        }

        protected int last_version = -1;
        protected int last_caret_pos = -1;

        public void update_caret_pos()
        {
            int r, c, caret, vspace;

            vsTextView.GetCaretPos(out r, out c);
            vsTextView.GetNearestPosition(r, c, out caret, out vspace);

            if (last_caret_pos != caret)
            {
                calc_caret_pos();
            }
        }

        public int OnComboGetFocus(int iCombo)
        {
            refresh_if_needed();

            return 0;
        }

        public int OnItemSelected(int iCombo, int iIndex)
        {
            return 0;
        }

        protected IVsDropdownBar bar;
        public int SetDropdownBar(IVsDropdownBar pDropdownBar)
        {
            bar = pDropdownBar;

            return 0;
        }

        // temporary variable shared between all the pattern matching
        // functions.
        protected string file_data;
    }

}